package com.xyz.mockapi.common.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.read.listener.ReadListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class ExcelUtil {

    /**
     * 解析Excel，拦截类型转换错误并返回中文提示
     */
    public static <T> List<T> parseExcel(MultipartFile file, Class<T> clazz) throws IOException {
        List<T> dataList = new ArrayList<>();
        String fileName = file.getOriginalFilename();
        log.info("开始解析 Excel 文件：{}，类型：{}", fileName, clazz.getSimpleName());

        try (InputStream inputStream = file.getInputStream()) {
            EasyExcel.read(inputStream, clazz, new ReadListener<T>() {
                @Override
                public void invoke(T data, com.alibaba.excel.context.AnalysisContext context) {
                    dataList.add(data);
                }

                @Override
                public void doAfterAllAnalysed(com.alibaba.excel.context.AnalysisContext context) {
                    log.info("Excel 文件解析完成，共 {} 条数据", dataList.size());
                }

                // 关键：拦截解析时的异常（如类型转换错误）
                @Override
                public void onException(Exception exception, com.alibaba.excel.context.AnalysisContext context) {
                    if (exception instanceof ExcelDataConvertException) {
                        // 类型转换异常，提取关键信息
                        ExcelDataConvertException convertException = (ExcelDataConvertException) exception;
                        int rowNum = convertException.getRowIndex() + 1; // Excel行号（从1开始）
                        int columnIndex = convertException.getColumnIndex(); // 列索引（从0开始）
                        String errorValue = convertException.getCellData().getStringValue(); // 错误值
                        String fieldName = getFieldNameByColumnIndex(clazz, columnIndex); // 字段中文名称

                        // 拼接中文错误提示，直接抛出自定义异常
                        String errorMsg = String.format(
                                "第%d行，第%d列【%s】字段值【%s】错误：%s",
                                rowNum, columnIndex + 1, fieldName, errorValue, exception.getMessage()
                        );
                        log.error(errorMsg, exception);
                        throw new RuntimeException(errorMsg); // 抛给Controller捕获
                    }
                    // 其他异常直接抛出
                    throw new RuntimeException("Excel解析失败：" + exception.getMessage());
                }
            }).sheet().doRead();
        } catch (RuntimeException e) {
            // 捕获onException中抛出的中文错误提示
            throw new RuntimeException(e.getMessage());
        }

        return dataList;
    }

    /**
     * 根据列索引获取字段的中文名称（从@ExcelProperty的value中提取）
     */
    private static <T> String getFieldNameByColumnIndex(Class<T> clazz, int columnIndex) {
        // 遍历实体类所有字段，找到对应列索引的@ExcelProperty注解
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(ExcelProperty.class)) {
                ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
                if (excelProperty.index() == columnIndex) {
                    // 返回@ExcelProperty的value（如"队列状态 0未下发 1已下发 2已上线"）
                    return excelProperty.value()[0];
                }
            }
        }
        return "未知字段";
    }
}